<template>
  <div
    class="three-page"
    :class="$style.page"
    @dragenter="onDragenter"
    @dragover="onDragover"
    @dragleave="onDragleave"
    @drop="onDrop"
  >
    <div :class="$style['model-operate']">
      <div :class="$style.item">
        <div :class="$style.label">当前坐标</div>
        <div :class="$style.value">
          <el-input class="gui-text" type="textarea" v-model="modelOpts.dotText"></el-input>
        </div>
      </div>

      <div :class="$style.tree">
        <el-tree
          :data="modelOpts.uploadList"
          :expand-on-click-node="false"
          @node-click="onTreeClick"
        >
          <template #default="{ node, data }">
            <div :class="$style['tree-node']">
              <span :class="$style.label">{{ node.label }}</span>
              <el-link
                :class="$style.btn"
                type="danger"
                :icon="Delete"
                @click="onTreeDelete(data)"
              ></el-link>
            </div>
          </template>
        </el-tree>
      </div>
    </div>

    <input :class="$style.upload" type="file" @change="onFileChange" />
    <input :class="$style.upload" type="file" @change="onHdrChange" />

    <div :class="$style.tip">
      控制器键盘操作 W：位移；E：旋转；R：缩放；+、-：控制器大小；X：x 轴切换；Y：y 轴切换；Z：z
      轴切换；空格：控制器锁定；
    </div>

    <drop-upload v-if="dropOpts.droping" />

    <div class="h-100" ref="containerRef"></div>
  </div>
</template>

<script lang="ts" setup>
import { Delete } from '@element-plus/icons-vue'
import dropUpload from './components/drop-upload.vue'

import { modelOpts } from './modules/store'
import { Scene } from './class'
import { getPageOpts, getUploadOpts } from './data'
import { base } from './data/methods'
import { useResize } from '@/hooks/scene-resize'
import type { GroupTreeItem } from './modules/type'
import { Message } from '@/utils/element'
import { Hooks } from 'three-scene'

const pageOpts = reactive(getPageOpts())

const { uploadModel } = Hooks.useUpload({
  baseUrl: base
})

const containerRef = ref()
const options: ConstructorParameters<typeof Scene>[0] = {
  baseUrl: base,
  env: pageOpts.env,
  grid: {
    visible: true,
    fork: true
  },
  render: {
    alpha: true
  },
  camera: {
    position: [-50, 50, 100]
  },
  axes: {
    visible: true
  }
}
let scene: InstanceType<typeof Scene>

const dropOpts = reactive({
  droping: false
})

// 阻止默认事件
const preventDefaults = (e: DragEvent) => {
  e.preventDefault()
  e.stopPropagation()
}

// 拖拽上传
const onDragenter = (e: DragEvent) => {
  preventDefaults(e)
  dropOpts.droping = true
}
// 拖进
const onDragover = (e: DragEvent) => {
  preventDefaults(e)
  dropOpts.droping = true
}
// 离开
const onDragleave = (e: DragEvent) => {
  preventDefaults(e)
  dropOpts.droping = false
}
// 拖拽
const onDrop = (e: DragEvent) => {
  preventDefaults(e)
  dropOpts.droping = false

  const dt = e.dataTransfer
  const files = dt?.files
  console.log(files)
  if (!files) return
  for (let i = 0; i < files.length; i++) {
    upload(files[i])
  }
}

// 树结构点击
const onTreeClick = (e: GroupTreeItem) => {
  scene?.modules.mian?.selectModel(e)
}

// 删除树结构
const onTreeDelete = (e: GroupTreeItem) => {
  scene?.modules.mian?.deleteModel(e)
}

// 校验文件类型
const validateFileType = (filename: string) => {
  const type = filename.split('.').pop()?.toLowerCase() || ''
  if (!uploadOpts.accept.includes(type)) {
    Message(`${filename} 文件格式不正确,转换格式支持 ${uploadOpts.accept.join('、')}！`, 'error')
    return false
  }
  return true
}

// 上传
const upload = (file: File) => {
  let filename = file.name
  if (!validateFileType(filename)) return

  filename = file.name.substring(0, file.name.lastIndexOf('.'))
  uploadOpts.fileName = filename
  uploadModel(
    [file],
    model => {
      console.log(file.name, model)
      scene.modules.mian?.uploadedModel(model, filename)
    },
    ({ progress, size, filename }) => {
      console.log('Loading', filename, size, progress)
    }
  )
}

// 上传
const uploadOpts = reactive(getUploadOpts())
const onFileChange = (e: Event) => {
  console.log(e)
  const files = (e.target as HTMLInputElement).files
  if (!files?.length) return
  const file = files[0] as File
  upload(file)
  ;(e.target as HTMLInputElement).value = ''
}

// 上传 hdr
const onHdrChange = (e: Event) => {
  const files = (e.target as HTMLInputElement).files
  if (!files?.length) return
  const file = files[0] as File
  const filename = file.name

  const type = filename.split('.').pop()?.toLowerCase() || ''
  const types = ['hdr', 'exr']
  if (!types.includes(type)) {
    Message(`${filename} 文件格式不正确,转换格式支持 ${types.join('、')}！`, 'error')
    return false
  }

  scene.modules.env?.fileToEnv(file)
}

onMounted(() => {
  options.container = containerRef.value
  scene = new Scene(options, {
    addGroupCall: list => {
      console.log(list)
    }
  })
  scene.run()

  console.log(scene)

  useResize(scene).resize()
})
</script>

<style lang="scss" module>
@use './style.scss';
</style>
